//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.eResearch.Ontology.Lookup
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using Intellidimension.Rdf;

    /// <summary>
    /// This class implements <see cref="IOntologyLookupTable"/> interface and performs lookup from file storage.
    /// </summary>
    public class FileOntologyLookupTable : IOntologyLookupTable
    {
        /// <summary>
        /// Instance of the lookup table.
        /// </summary>
        private Dictionary<string, string> conceptLookupTable = new Dictionary<string, string>();

        /// <summary>
        /// Initializes a new instance of the FileOntologyLookupTable class.
        /// </summary>
        public FileOntologyLookupTable()
        {
            // Populate the lookup index
            PopulateLookUpIndex();            
        }

        /// <summary>
        /// Performs lookup using the property qualified name.
        /// </summary>
        /// <param name="propertyQualifiedName">Property qualified name.</param>
        /// <returns>The concept name.</returns>
        public string MapPropertyToConcept(string propertyQualifiedName)
        {
            if (conceptLookupTable.ContainsKey(propertyQualifiedName))
            {
                return conceptLookupTable[propertyQualifiedName];
            }

            return null;
        }

        /// <summary>
        /// Performs lookup using the object type and property name.
        /// </summary>
        /// <param name="objectType">Type of the object.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <returns>The concept name.</returns>
        public string MapPropertyToConcept(Type objectType, string propertyName)
        {
            if (objectType == null)
            {
                return null;
            }

            string conceptName = MapPropertyToConcept(CreatePropertyQualifiedName(objectType, propertyName));
            if (conceptName == null)
            {
                conceptName = MapPropertyToConcept(objectType.BaseType, propertyName);
            }

            return conceptName;
        }

        /// <summary>
        /// Creates property qualified name from the type and property name.
        /// </summary>
        /// <param name="objectType">Type of the object.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <returns>Property qualified name.</returns>
        private static string CreatePropertyQualifiedName(Type objectType, string propertyName)
        {
            return String.Format(CultureInfo.CurrentUICulture, "{0}.{1}", objectType.FullName, propertyName);
        }

        /// <summary>
        /// Popluates the lookup table index from file store.
        /// </summary>
        private void PopulateLookUpIndex()
        {
            // Read the TriTon OWL file and populate the lookup data structure
            // Given a class in the TriTon ontology, the corresponding Windows Workflow class name is
            // accessed via the rdfs:label relationship
            try
            {
                GraphDataSource rdfSource = new GraphDataSource();

                // Create a resource manager to access the Trident Ontology resource
                System.Resources.ResourceManager tronRM = new System.Resources.ResourceManager("TridentOntology", System.Reflection.Assembly.GetExecutingAssembly());

                // File path hardcoded - needs to be specified as part of configuration
                rdfSource.Read<RdfXmlReader>(File.ReadAllText(tronRM.GetObject("Trident_082508.owl").ToString()));

                // List all classes in the RDF graph
                foreach (RdfNode node in rdfSource.GetSubjects())
                {
                    foreach (RdfUri property in node.GetPredicates())
                    {
                        // Get the label value of the concept - use the RDFS label property
                        if (property.ToString().Contains("http://www.w3.org/2000/01/rdf-schema#label") == true)
                        {
                            // Console.WriteLine("Concept: " + node.ToString() + "--");
                            // A concept may have multiple labels associated with it
                            foreach (RdfValue val in node[property])
                            {
                                // Console.WriteLine("WF: " + val + "\n");
                                // Add the concept label as the "key" and the concept as the "value"
                                conceptLookupTable.Add(val, node.Value);
                            }
                        }
                    }
                }

                // Print out the contents of the lookup index
                // foreach(string dVal in m_ConceptLookupTable.Keys)
                // {
                //      Console.WriteLine("key: " + dVal + ", value: " + m_ConceptLookupTable[dVal] + "\n");
                // }
            }
            catch (IndexOutOfRangeException e)
            {
                Console.Write(e.ToString());
            }
        }
    }
}
